﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FreeRedis;
using LeoGemini.Service.Infrastructure.Extension;
using LeoGemini.Service.Infrastructure.Handler.Exception;
using MailService.Application.Contract.DTO.Output;
using MailService.Application.Contract.IAppService;
using MailService.Domain.Aggregate.Mail;
using MailService.Domain.Repository;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Services;

namespace MailService.Application.AppService
{
    public class MailAppService : ApplicationService, IMailAppService
    {
        private readonly IMailRepository _mailRepository;
        private readonly RedisClient _cache;

        public MailAppService(
            IMailRepository mailRepository,
            RedisClient cache)
        {
            _mailRepository = mailRepository;
            _cache = cache;
        }
        
        /// <summary>
        /// 分页获取邮件id
        /// </summary>
        public async Task<ICollection<string>> GetMailByPaginationAsync(int p, int n)
        {
            // 分页索引不正确
            if (p < 0)
                throw new BadRequestException(ErrorMessage.PAGINATION_PEGE_ERROR);

            var mailIds = new List<string>(
                _cache.ZRange("mailIds", p * n, p * n + n - 1));

            if (mailIds.Count == 0)
            {
                var mails = await _mailRepository
                    .OrderBy(mail => mail.CreationTime)
                    .Skip(p * n).Take(n).ToListAsync();
                
                // 缓存结果
                foreach (var data in mails)
                {
                    _cache.ZAdd("mailIds",
                        data.CreationTime.ToUnixTimeTicks(), data.Id.ToString());
                    mailIds.Add(data.Id.ToString());
                }
            }

            return mailIds;
        }

        /// <summary>
        /// 邮件id获取邮件信息
        /// </summary>
        public async Task<GetMailReturnDto> GetMailByIdAsync(Guid id)
        {
            var mail = await _cache.CacheOrGetAsync($"mails:{id}",
                async () => await _mailRepository.FindAsync(id));

            // 邮件不存在
            if (mail == null)
                throw new NotFoundException(ErrorMessage.MAIL_NOT_FOUND);

            return ObjectMapper.Map<Mail, GetMailReturnDto>(mail);
        }

        /// <summary>
        /// 邮件id删除邮件
        /// </summary>
        public async Task DeleteMailByIdAsync(Guid id)
        {
            var mail = await _cache.CacheOrGetAsync($"mails:{id}",
                async () => await _mailRepository.FindAsync(id));
            
            // 邮件不存在
            if (mail == null)
                throw new NotFoundException(ErrorMessage.MAIL_NOT_FOUND);

            await _cache.RemoveAndPersistAsync(
                async () =>
                {
                    _cache.ZRem("mailIds", mail.Id.ToString());
                    await _mailRepository.DeleteAsync(mail);
                }, $"mails:{id}");
        }
    }
}